#include<iostream>
#include<unistd.h>
#include<cstdlib>
#include<time.h>
#include<vector>
#include<string>
#include<unordered_map>
#include<sys/types.h>
#include<sys/wait.h>
#include<utility>

using namespace std;

typedef void(*functor)();
vector<functor>functors;
unordered_map<int,string> info; 
vector<pair<int,int>> free_info;


void f1()
{
    cout<<"方法1"<<endl;
}

void f2()
{
    cout<<"方法2"<<endl;
}

void f3()
{
    cout<<"方法3"<<endl;
}

void LoadFunctors()
{
    functors.push_back(f1);
    info.insert({functors.size(),"方法1"});
    functors.push_back(f2);
    info.insert({functors.size(),"方法2"});
    functors.push_back(f3);
    info.insert({functors.size(),"方法3"});

    cout<<"方法集加载成功"<<endl;
}

void work(int fd)
{
    while(1)
    {
        int tag=0;
        int dia=read(fd,&tag,sizeof(tag));
        if(dia==4)
        {
            cout<<"pid: "<<getpid()<<" 执行任务: ";
            functors[tag]();
        }
        else if(dia==0)
        {
            cout<<"pid: "<<getpid()<<" 任务执行结束"<<endl;
            break;
        }
        else
        {
            //DO NOTHING
        }
    }
}

void send(vector<pair<int,int>> _info)
{
    srand(time(nullptr));
    while(1)
    {
        int tag1=random()%_info.size();
        int tag2=random()%functors.size();

        write(_info[tag1].second,&tag2,sizeof(tag2));
        sleep(1);
        cout<<"父进程分配给子进程 pid: "<<_info[tag1].first<<"任务编号: "<<tag2+1<<endl;
    }
}

int main()
{
    //加载方法集
    LoadFunctors();
    //循环创建多个子进程
    int cnt=3;
    for(int i=0;i<cnt;i++)
    {
        int pipefd[2]={0};
        pipe(pipefd);
        pid_t id=fork();
        if(id==0)
        {
            //关闭写端
            close(pipefd[1]);
            //子进程，执行任务
            work(pipefd[0]);
            close(pipefd[0]);
            exit(0);
        }
        //父进程关闭读端
        close(pipefd[0]);
        //保存子进程pid,父进程的写端文件描述符
        free_info.push_back(pair<int,int>(id,pipefd[1]));


    }
    //父进程分配任务
    send(free_info);
    //关闭父进程写端，回收子进程
    for(int i=0;i<cnt;i++)
    {
        int status=0;
        close(free_info[i].second);
        waitpid(free_info[i].first,&status,0);
    }
    return 0;
}